import subprocess
import platform
import time
import logging
from django.utils import timezone
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from .models import City, DataCenter, Host, HostPassword, HostPingLog
from .serializers import (
    CitySerializer, DataCenterSerializer, DataCenterDetailSerializer,
    HostSerializer, HostDetailSerializer, HostPasswordSerializer,
    HostPingLogSerializer, PingRequestSerializer
)
from django.shortcuts import render
from .services import PasswordManager, BulkPasswordManager

logger = logging.getLogger(__name__)


class CityViewSet(viewsets.ModelViewSet):
    """城市视图集"""
    queryset = City.objects.all()
    serializer_class = CitySerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = City.objects.all()
        name = self.request.query_params.get('name', None)
        if name:
            queryset = queryset.filter(name__icontains=name)
        return queryset


class DataCenterViewSet(viewsets.ModelViewSet):
    """机房视图集"""
    queryset = DataCenter.objects.all()
    serializer_class = DataCenterSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = DataCenter.objects.all()
        city_id = self.request.query_params.get('city_id', None)
        if city_id:
            queryset = queryset.filter(city_id=city_id)
        return queryset
    
    def get_serializer_class(self):
        if self.action == 'retrieve':
            return DataCenterDetailSerializer
        return DataCenterSerializer


class HostViewSet(viewsets.ModelViewSet):
    """主机视图集"""
    queryset = Host.objects.all()
    serializer_class = HostSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = Host.objects.all()
        status_filter = self.request.query_params.get('status', None)
        data_center_id = self.request.query_params.get('data_center_id', None)
        city_id = self.request.query_params.get('city_id', None)
        
        if status_filter:
            queryset = queryset.filter(status=status_filter)
        if data_center_id:
            queryset = queryset.filter(data_center_id=data_center_id)
        if city_id:
            queryset = queryset.filter(data_center__city_id=city_id)
            
        return queryset
    
    def get_serializer_class(self):
        if self.action == 'retrieve':
            return HostDetailSerializer
        return HostSerializer
    
    @action(detail=True, methods=['post'])
    def ping(self, request, pk=None):
        """ping主机探测"""
        try:
            host = self.get_object()
            result = self._ping_host(host.ip_address)
            
            # 更新主机状态
            host.last_ping_time = timezone.now()
            host.last_ping_status = result['is_reachable']
            host.save()
            
            # 记录ping日志
            HostPingLog.objects.create(
                host=host,
                is_reachable=result['is_reachable'],
                response_time=result.get('response_time'),
                error_message=result.get('error_message', '')
            )
            
            return Response({
                'host_id': host.id,
                'hostname': host.hostname,
                'ip_address': host.ip_address,
                'is_reachable': result['is_reachable'],
                'response_time': result.get('response_time'),
                'error_message': result.get('error_message', ''),
                'ping_time': timezone.now()
            })
            
        except Exception as e:
            logger.error(f"Ping host error: {str(e)}")
            return Response(
                {'error': f'Ping失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    def _ping_host(self, ip_address):
        """执行ping操作"""
        try:
            if platform.system().lower() == "windows":
                # Windows系统
                command = ['ping', '-n', '1', '-w', '1000', ip_address]
            else:
                # Linux/Unix系统
                command = ['ping', '-c', '1', '-W', '1', ip_address]
            
            start_time = time.time()
            result = subprocess.run(
                command,
                capture_output=True,
                text=True,
                timeout=5
            )
            end_time = time.time()
            
            if result.returncode == 0:
                response_time = (end_time - start_time) * 1000  # 转换为毫秒
                return {
                    'is_reachable': True,
                    'response_time': round(response_time, 2)
                }
            else:
                return {
                    'is_reachable': False,
                    'error_message': result.stderr or 'Ping失败'
                }
                
        except subprocess.TimeoutExpired:
            return {
                'is_reachable': False,
                'error_message': 'Ping超时'
            }
        except Exception as e:
            return {
                'is_reachable': False,
                'error_message': str(e)
            }
    @action(detail=True, methods=['post'])
    def change_password(self, request, pk=None):
        """修改主机密码"""
        try:
            host = self.get_object()
            new_password = request.data.get('password')
            
            password_manager = PasswordManager()
            success, result_password = password_manager.change_host_password(host, new_password)
            
            if success:
                return Response({
                    'success': True,
                    'message': f'主机 {host.hostname} 密码修改成功',
                    'new_password': result_password
                })
            else:
                return Response({
                    'success': False,
                    'message': f'主机 {host.hostname} 密码修改失败'
                }, status=status.HTTP_400_BAD_REQUEST)
                
        except Exception as e:
            logger.error(f"修改主机密码时发生错误: {str(e)}")
            return Response({
                'success': False,
                'message': f'修改密码时发生错误: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=True, methods=['post'])
    def test_connection(self, request, pk=None):
        """测试SSH连接"""
        try:
            host = self.get_object()
            
            # 获取当前密码
            try:
                host_password = HostPassword.objects.get(host=host)
                current_password = host_password.get_password()
            except HostPassword.DoesNotExist:
                return Response({
                    'success': False,
                    'message': '主机没有密码记录'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 测试连接
            password_manager = PasswordManager()
            success = password_manager.test_ssh_connection(host, current_password)
            
            return Response({
                'success': success,
                'message': f'SSH连接测试{"成功" if success else "失败"}'
            })
            
        except Exception as e:
            logger.error(f"测试SSH连接时发生错误: {str(e)}")
            return Response({
                'success': False,
                'message': f'测试连接时发生错误: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=True, methods=['get'])
    def password_status(self, request, pk=None):
        """获取密码状态"""
        try:
            host = self.get_object()
            password_manager = PasswordManager()
            status_info = password_manager.get_password_status(host)
            
            return Response(status_info)
            
        except Exception as e:
            logger.error(f"获取密码状态时发生错误: {str(e)}")
            return Response({
                'success': False,
                'message': f'获取状态时发生错误: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class HostPasswordViewSet(viewsets.ModelViewSet):
    """主机密码视图集"""
    queryset = HostPassword.objects.all()
    serializer_class = HostPasswordSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        return HostPassword.objects.all()
    
    @action(detail=True, methods=['post'])
    def change_password(self, request, pk=None):
        """手动修改主机密码"""
        try:
            host_password = self.get_object()
            new_password = request.data.get('new_password')
            
            if not new_password:
                return Response(
                    {'error': '新密码不能为空'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            host_password.set_password(new_password)
            
            return Response({
                'message': '密码修改成功',
                'password_changed_at': host_password.password_changed_at,
                'next_change_time': host_password.next_change_time
            })
            
        except Exception as e:
            logger.error(f"Change password error: {str(e)}")
            return Response(
                {'error': f'密码修改失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class HostPingLogViewSet(viewsets.ReadOnlyModelViewSet):
    """主机ping日志视图集"""
    queryset = HostPingLog.objects.all()
    serializer_class = HostPingLogSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = HostPingLog.objects.all()
        host_id = self.request.query_params.get('host_id', None)
        is_reachable = self.request.query_params.get('is_reachable', None)
        
        if host_id:
            queryset = queryset.filter(host_id=host_id)
        if is_reachable is not None:
            queryset = queryset.filter(is_reachable=is_reachable.lower() == 'true')
            
        return queryset



    
    

class HostPasswordViewSet(viewsets.ModelViewSet):
    """主机密码管理视图集"""
    queryset = HostPassword.objects.all()
    serializer_class = HostPasswordSerializer
    permission_classes = [IsAuthenticated]
    
    @action(detail=False, methods=['post'])
    def bulk_change(self, request):
        """批量修改密码"""
        try:
            host_ids = request.data.get('host_ids', [])
            
            bulk_manager = BulkPasswordManager()
            
            if host_ids:
                # 根据指定主机ID列表修改
                result = bulk_manager.change_passwords_by_hosts(host_ids)
            else:
                # 修改所有过期的密码
                result = bulk_manager.change_all_expired_passwords()
            
            return Response({
                'success': True,
                'result': result
            })
            
        except Exception as e:
            logger.error(f"批量修改密码时发生错误: {str(e)}")
            return Response({
                'success': False,
                'message': f'批量修改密码时发生错误: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['get'])
    def expired_passwords(self, request):
        """获取所有过期的密码"""
        try:
            expired_passwords = HostPassword.objects.filter(
                next_change_time__lte=timezone.now()
            )
            
            expired_hosts = []
            for host_password in expired_passwords:
                expired_hosts.append({
                    'host_id': host_password.host.id,
                    'hostname': host_password.host.hostname,
                    'ip_address': host_password.host.ip_address,
                    'expired_at': host_password.next_change_time,
                    'password_age_hours': host_password.get_password_age()
                })
            
            return Response({
                'success': True,
                'expired_hosts': expired_hosts,
                'count': len(expired_hosts)
            })
            
        except Exception as e:
            logger.error(f"获取过期密码时发生错误: {str(e)}")
            return Response({
                'success': False,
                'message': f'获取过期密码时发生错误: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['post'])
    def initialize_all(self, request):
        """初始化所有主机的密码"""
        try:
            # 获取所有没有密码记录的主机
            hosts_without_password = []
            for host in Host.objects.all():
                if not HostPassword.objects.filter(host=host).exists():
                    hosts_without_password.append(host)
            
            if not hosts_without_password:
                return Response({
                    'success': True,
                    'message': '所有主机都已初始化密码',
                    'result': {'success': 0, 'failed': 0, 'total': 0}
                })
            
            # 初始化密码
            password_manager = PasswordManager()
            success_count = 0
            failed_count = 0
            
            for host in hosts_without_password:
                try:
                    success, new_password = password_manager.change_host_password(host)
                    if success:
                        success_count += 1
                    else:
                        failed_count += 1
                except Exception as e:
                    failed_count += 1
                    logger.error(f"初始化主机 {host.hostname} 密码失败: {str(e)}")
            
            result = {
                'success': success_count,
                'failed': failed_count,
                'total': success_count + failed_count
            }
            
            return Response({
                'success': True,
                'message': f'密码初始化完成，成功: {success_count}/{len(hosts_without_password)}',
                'result': result
            })
            
        except Exception as e:
            logger.error(f"初始化密码时发生错误: {str(e)}")
            return Response({
                'success': False,
                'message': f'初始化密码时发生错误: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
